package de.rj.urwalking.ui.activities;

import java.util.ArrayList;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.threed.jpct.Matrix;

import de.rj.urwalking.R;
import de.rj.urwalking.config.Config;
import de.rj.urwalking.data.Experiment;
import de.rj.urwalking.data.survey.Question;
import de.rj.urwalking.data.survey.Question.OnAnswerChangedListener;
import de.rj.urwalking.data.survey.SalientObjectSurvey;
import de.rj.urwalking.db.DBSalientObject;
import de.rj.urwalking.ui.fragments.OrientationCheckFragment;
import de.rj.urwalking.ui.fragments.OrientationCheckFragment.OnOrientationConfirmedListener;
import de.rj.urwalking.ui.fragments.dialog.CancelSurveyDialog;
import de.rj.urwalking.ui.fragments.QuestionsFragment;
import de.rj.urwalking.util.ExperimentManager;
import de.rj.urwalking.util.PrefUtil;
import de.rj.urwalking.util.Util;

/**
 * Activity that is used to show the {@link SalientObjectSurvey}. It contains a {@link QuestionsFragment} displaying the
 * {@link Question} s and some UI elements to control the survey. At the beginning, a {@link OrientationCheckFragment}
 * is shown.
 * 
 * @author rjj
 * 
 */

public class QuestionsActivity extends SherlockFragmentActivity implements OnOrientationConfirmedListener,
		OnAnswerChangedListener {

	private SalientObjectSurvey survey;
	private DBSalientObject referencedObject;

	private TextView screenProgressTextView;
	private Button nextScreenButton;
	private Button previousScreenButton;
	private RelativeLayout surveyControlLayout;
	private Button finishSurveyButton;
	private TextView questionProgressTextView;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_questions);

		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		checkReferencedObject();
		initUI();
		initSurvey();

		if (ExperimentManager.getInstance().getCurrentExperiment().hasPreviousObject()
				&& PrefUtil.readBoolean(R.string.key_pref_orientation_check, this, false)) {
			showOrientationCheckFragment();
		} else {
			showQuestions();
		}

	}

	/**
	 * Overrides the default behaviour of the back button and displays a confirmation dialog.
	 */
	@Override
	public void onBackPressed() {

		new CancelSurveyDialog().show(getSupportFragmentManager(), "CancelSurveyDialog");

	}

	private void initUI() {
		screenProgressTextView = (TextView) findViewById(R.id.screenProgressTextView);
		questionProgressTextView = (TextView) findViewById(R.id.questionProgressTextView);
		nextScreenButton = (Button) findViewById(R.id.nextScreenButton);
		previousScreenButton = (Button) findViewById(R.id.previousScreenButton);
		finishSurveyButton = (Button) findViewById(R.id.finishSurveyButton);
		nextScreenButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showNextScreen();
				previousScreenButton.setEnabled(true);
				nextScreenButton.setEnabled(false);

				if (survey.getCurrentScreenNr() == survey.getScreenCount()) {
					nextScreenButton.setVisibility(View.INVISIBLE);
					finishSurveyButton.setVisibility(View.VISIBLE);
					finishSurveyButton.setEnabled(false);
				}

			}
		});
		previousScreenButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showPreviousScreen();
				if (survey.getCurrentScreenNr() == 1) {
					previousScreenButton.setEnabled(false);
				}
				nextScreenButton.setVisibility(View.VISIBLE);
				finishSurveyButton.setVisibility(View.INVISIBLE);

			}
		});

		finishSurveyButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				finishSurvey();
			}
		});

		surveyControlLayout = (RelativeLayout) findViewById(R.id.surveyControlLayout);

		Util.setupTouchListeners(findViewById(R.id.questionsRootLayout), this);
	}

	/**
	 * Register touch listeners for all Views except EditTexts in order to hide the keyboard.
	 * http://stackoverflow.com/questions/4165414/how-to-hide-soft-keyboard-on-android-after-clicking-outside-edittext
	 * 
	 * @param view
	 */

	private void checkReferencedObject() {

		Bundle extras = getIntent().getExtras();
		referencedObject = (DBSalientObject) extras.getSerializable("object");

	}

	private void initSurvey() {

		survey = ExperimentManager.getInstance().getEmptySalientObjectSurvey();
		survey.setTimestamp(System.currentTimeMillis());
		survey.setReferencedObject(referencedObject);
		survey.setProjectionMatrix((Matrix) getIntent().getSerializableExtra("projectionMatrix"));
		survey.setLocation(getIntent().getDoubleExtra("currentLatitude", 0),
				getIntent().getDoubleExtra("currentLongitude", 0));
		survey.setCallbackForQuestions(this);
	}

	private void finishSurvey() {

		Toast.makeText(QuestionsActivity.this, getString(R.string.finished_survey), Toast.LENGTH_SHORT).show();

		survey.finish();

		Experiment experiment = ExperimentManager.getInstance().getCurrentExperiment();
		experiment.addSalientObjectSurvey(survey);

		// check preferences if we actually want to save the data
		boolean saveData = PrefUtil.readBoolean(R.string.key_pref_test_mode_save_data, this, true);
		if (saveData) {
			experiment.saveResultsXML(false, -1000);
		} else {
			if (Config.DEBUG) Log.d(Config.TAG, "Not saving data to XML as set in preferences");
		}
		Intent data = new Intent();
		data.putExtra("name", referencedObject.getName());
		setResult(RESULT_OK, data);
		finish();

	}

	public void abortSurvey() {

		Experiment experiment = ExperimentManager.getInstance().getCurrentExperiment();
		experiment.addSalientObjectSurvey(survey);

		setResult(RESULT_CANCELED);
		finish();
	}

	private void showQuestions() {

		ArrayList<Question> questions = survey.getCurrentQuestions();
		surveyControlLayout.setVisibility(View.VISIBLE);

		replaceScreen(questions);

		updateProgress();

	}

	private void showNextScreen() {

		survey.nextScreen();

		ArrayList<Question> nextQuestions = survey.getCurrentQuestions();

		replaceScreen(nextQuestions);
		updateProgress();

	}

	protected void showPreviousScreen() {

		survey.previousScreen();
		getSupportFragmentManager().popBackStack();
		updateProgress();
	}

	private void replaceScreen(ArrayList<Question> questions) {

		Fragment fragment = new QuestionsFragment();
		Bundle args = new Bundle();
		args.putSerializable("questions", questions);
		fragment.setArguments(args);

		FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

		ft.setCustomAnimations(R.anim.fragment_slide_left_enter, R.anim.fragment_slide_left_exit,
				R.anim.fragment_slide_right_enter, R.anim.fragment_slide_right_exit);

		ft.replace(R.id.fragment, fragment);
		ft.addToBackStack(null);
		ft.commit();

	}

	private void updateProgress() {
		screenProgressTextView.setText("Seite " + survey.getCurrentScreenNr() + "/" + survey.getScreenCount());
		questionProgressTextView.setText(survey.getNumCurrentlyAnsweredQuestions() + "/"
				+ survey.getNumCurrentlyAnswerableQuestions() + " Fragen beantwortet");
	}

	private void showOrientationCheckFragment() {
		Fragment fragment = new OrientationCheckFragment();
		FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
		ft.add(R.id.fragment, fragment).commit();
	}

	/**
	 * Called when the user presses the arrow that points to the previous landmark.
	 */
	@Override
	public void onOrientationConfirmed(float orientation, long startTimestamp, long endTimestamp) {

		survey.setOrientation(orientation);
		survey.setStartTimestamp(startTimestamp);
		survey.setEndTimestamp(endTimestamp);

		showQuestions();
	}

	/**
	 * Called whenever an answer is changed in the {@link QuestionsFragment}.
	 */
	@Override
	public void onAnswerChanged() {

		if (survey.areCurrentQuestionsAnswered()) {
			nextScreenButton.setEnabled(true);
			finishSurveyButton.setEnabled(true);
		} else {
			nextScreenButton.setEnabled(false);
			finishSurveyButton.setEnabled(false);
		}

		updateProgress();

	}

}
